package hust.hiepdv.javaproject.model;

import hust.hiepdv.javaproject.collisionphysics.CollisionPhysics;
import hust.hiepdv.javaproject.collisionphysics.CollisionResponse;

import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.util.Formatter;
import java.util.Random;

public class Ball{

	public static final int STYLE_1 = 1;
	public static final String STYLE_1_DIR = "pic\\ball_style_1.png";

	float x;
	float y;
	Image image;
	private Player previousPlayer = null;
	Random random = new Random();	
	private float speedX = random.nextInt(3)+ 3;	
	private float speedY = random.nextInt(3)+ 3;
	private float radius = 12.5f;
	private float centerX, centerY;
	private float timeUpdate = 1.0f;
	private int impactX, impactY;
	private boolean hasCollided = false;

	private CollisionResponse earliestCollisionResponse = new CollisionResponse();
	private CollisionResponse tempCollisionResponse = new CollisionResponse();
	
	public Ball(){
		
	}

	public Ball(float x, float y, Image image) {
		this.x = x;
		this.y = y;
		this.image = image;
	}

	/*public Ball(float x, float y, int style) {
		this(x,y,null);
		Image image = null;
		switch (style) {
		case STYLE_1:
			image = Toolkit.getDefaultToolkit().getImage(STYLE_1_DIR);
			break;
		default:
			break;
		}
		centerX = x + radius;
		centerY = y + radius;		
		this.image = image;		
	}	*/
	
	public Ball(float centerx,float centery, int style){
		this.centerX = centerx;
		this.centerY = centery;
		
		Image image = null;
		switch (style) {
		case STYLE_1:
			image = Toolkit.getDefaultToolkit().getImage(STYLE_1_DIR);
			break;
		default:
			break;
		}
		x = centerX - radius;
		y = centerY - radius;		
		this.image = image;	
	}
	
	public void setData(float centerx,float centery, int style){
		this.centerX = centerx;
		this.centerY = centery;
		
		Image image = null;
		switch (style) {
		case STYLE_1:
			image = Toolkit.getDefaultToolkit().getImage(STYLE_1_DIR);
			break;
		default:
			break;
		}
		x = centerX - radius;
		y = centerY - radius;		
		this.image = image;	
	}

	public void intersect(Rectangle rec) {
		CollisionPhysics.pointIntersectsRectangleOuter(centerX, centerY,
				speedX, speedY, radius, rec.x, rec.y, rec.x + rec.width, rec.y
						+ rec.height, timeUpdate, tempCollisionResponse);
		if (tempCollisionResponse.t < earliestCollisionResponse.t) {
			earliestCollisionResponse.copy(tempCollisionResponse);
		}
	}

	public void intersect(Table table) {
		CollisionPhysics.pointIntersectsPolygon(centerX, centerY, speedX,
				speedY, radius, table.polyXs, table.polyYs,
				table.polyXs.length, timeUpdate, tempCollisionResponse);
		if (tempCollisionResponse.t < earliestCollisionResponse.t) {
			earliestCollisionResponse.copy(tempCollisionResponse);
		}
	}

	public void intersect(Pad pad) {
		CollisionPhysics.pointIntersectsPolygon(centerX, centerY, speedX,
				speedY, radius, pad.getPolyXs(), pad.getPolyYs(), 4, timeUpdate,
				tempCollisionResponse);
		if (tempCollisionResponse.t < earliestCollisionResponse.t) {
			earliestCollisionResponse.copy(tempCollisionResponse);
		}
	}

	public void update() {
		if (earliestCollisionResponse.t <= timeUpdate) {
			this.impactX = (int) (earliestCollisionResponse.getImpactX(this.centerX, speedX) - radius);
			this.impactY = (int) (earliestCollisionResponse.getImpactX(this.centerY, speedY) - radius);
			this.hasCollided = true;
			this.centerX = earliestCollisionResponse.getNewX(this.centerX,
					speedX);
			this.centerY = earliestCollisionResponse.getNewY(this.centerY,
					speedY);
			this.speedX = earliestCollisionResponse.newSpeedX;
			this.speedY = earliestCollisionResponse.newSpeedY;
			
		} else {
			this.centerX += this.speedX;
			this.centerY += this.speedY;
		}

		this.x = this.centerX - radius;
		this.y = this.centerY - radius;

		earliestCollisionResponse.reset();
	}
	
	/** Describe itself. */
	public String toString() {
		sb.delete(0, sb.length());
		formatter.format("@(%3.0f,%3.0f) r=%3.0f V=(%2.0f,%2.0f) ", (float)impactX, (float)impactY, radius, speedX, speedY);
		return sb.toString();
	}

	private StringBuilder sb = new StringBuilder();
	private Formatter formatter = new Formatter(sb);

	public void move() {
		this.x += this.speedX;
		this.y += this.speedY;
	}

	public Player getPreviousPlayer() {
		return previousPlayer;
	}

	public void setPreviousPlayer(Player previousPlayer) {
		this.previousPlayer = previousPlayer;
	}

	public float getspeedX() {
		return speedX;
	}

	public void setspeedX(float speedX) {
		this.speedX = speedX;
	}

	public float getspeedY() {
		return speedY;
	}

	public void setspeedY(float speedY) {
		this.speedY = speedY;
	}

	public void setEarliestCollisionResponse(
			CollisionResponse earliestCollisionResponse) {
		this.earliestCollisionResponse = earliestCollisionResponse;
	}

	public CollisionResponse getEarliestCollisionResponse() {
		return earliestCollisionResponse;
	}

	public float getX() {
		return x;
	}

	public void setX(float x) {
		this.x = x;
	}

	public float getY() {
		return y;
	}

	public void setY(float y) {
		this.y = y;
	}
	
	public void setImage(Image image) {
		this.image = image;
	}

	public Image getImage() {
		return image;
	}

	public int getImpactX() {
		return impactX;
	}

	public boolean isHasCollided() {
		return hasCollided;
	}

	public void setHasCollided(boolean hasCollided) {
		this.hasCollided = hasCollided;
	}

	public void setImpactX(int impactX) {
		this.impactX = impactX;
	}

	public int getImpactY() {
		return impactY;
	}

	public void setImpactY(int impactY) {
		this.impactY = impactY;
	}
}
